//手写promise
// promise A+规则
const PENDING = 'peding'
const FULLFILLED = 'fullfilled'
const REJECTED = 'rejected'
/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列
 * @param {Function} callback 
 */
function runMicroTask(callback) {
  // setTimeout(callback,0);
  // 判断node环境
  if(process && process.nextTick){
    process.nextTick(callback)
  }else if(MutationObserver){
    const p = document.createElement('p')
    const observer =  new MutationObserver(callback)
    observer.observe(p,{
      childList:true
    })
    p.innerHTML = '1'
  }else{
    setTimeout(callback,0);
  }
 
}
/**
 * 判断一个数据是不是promise对象
 * @param {*} obj 
 * @returns 
 */
function isPromise(obj){
    return !!(obj && typeof obj === 'object' && typeof obj.then === 'function')
}
class MyPromise {
  /**
   * 创建一个Promise
   * @param {*} executor  任务执行器 这个函数立即执行
   */
  constructor(executor){
    this._state = PENDING;
    this._value = undefined;
    this._handlers = [] //处理函数的队列
   
    // const resolve 
    try{
      executor(this._resolve.bind(this),this._reject.bind(this))
    }
    catch(error){
      this._reject(error)
    }
   
  }
 /**
  * 向处理队列中添加一个函数
  * @param {Function} executor 
  * @param {String} state
  * @param {Function} resolve 让then函数返回成功
  * @param {Function} reject 让then函数返回失败 
  */
  _pushHandlers(executor,state,resolve,reject){
      this._handlers.push({
        executor,
        state,
        resolve,
        reject
      })
  }
  /**
   * 
   * @returns 根据实际情况处理队列
   */
  _runHandlers(){
      if(this._state === PENDING)return; // 状态不一致 达不到执行条件
      console.log(`处理${this._handlers.length}个函数`)
      console.log(this._handlers)
      while(this._handlers[0]){
        this._runOneHanlder(this._handlers[0])
        this._handlers.shift()
      }
      // for(const hanler of this._handlers){
      //   // console.log(hanler)
       
       

      // }
  }
  /**
   * 
   * @param {Function} hanlder  处理单个hanlder
   */
  _runOneHanlder({executor,state,resolve,reject}){
   runMicroTask(()=>{
      if(this._state !== state){
        // 状态不一致，不处理
        return;
        
      }
      console.log(this._state)
      // console.log(hanlder)
      if(typeof executor !== 'function'){
        //传递后序处理并非一个函数
        this._state === FULLFILLED?resolve(this._value):reject(this._value)
        return;
      }
      try{
        const result = executor(this._value)
        // console.log('isPromise',isPromise(result),result)
        if(isPromise(result)){
          result.then(resolve,reject)
        }else{
          resolve(result)
        }
       
      }
      catch(error){
        reject(error)
      }
   })
  }
  /**
   * 
   * @param {Function} onFulfilled 
   * @param {Function} onRejected 

   */
  then(onFulfilled,onRejected){
    return new MyPromise((resolve,reject)=>{
      this._pushHandlers(onFulfilled,FULLFILLED,resolve,reject)
      this._pushHandlers(onRejected, REJECTED,resolve,reject)
      this._runHandlers() // 执行队列
    })
  }
  /**
   * catch捕获失败回调
   * @param {Function} onRejected 
   */
  catch(onRejected){
   return this.then(null,onRejected)
  }
/**
 * 
 * @param {Function} onSettled 
 */
  finally(onSettled){
    return this.then((data)=>{
      onSettled()
      return data
    },(reason)=>{
      onSettled()
      throw reason
    })
  }
   /**
   * 
   * @param {*} newState  新的状态
   * @param {*} value  相关数据
   */
   _changeState(newState,value){
    if(this._state != PENDING)return;
      this._state = newState;
      this._value = value
      this._runHandlers() // 状态变化执行队列
       
   }
/**
 * 标记当前任务完成
 * @param {any} data 任务成功的相关数据
 */
  _resolve(data){
      console.log('成功',data)
      //改变状态和数据
      this._changeState(FULLFILLED,data)
  }
 
  /**
 * 标记任务失败
 * @param { any }  reason 任务失败的相关数据
 */
  _reject(reason){
    console.log('失败',reason)
    //改变状态和数据
    this._changeState(REJECTED,reason)

  }
}


// const p = new MyPromise((resolve,reject)=>{
// // setTimeout(() => {
//   resolve(1234)

//   // debugger
// // });
// })  
// const p2 = p.finally(()=>{
  
// })

// setTimeout(() => {
//     console.log(p2)
// }, 50);


new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
.then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
        console.log("内部promise");
        resolve();
    })
    .then(() => {
        console.log("内部第一个then");
    })
    .then(() => {
        console.log("内部第二个then");
    });
    return new Promise((resolve, reject) => {
        console.log("内部promise2");
        resolve();
    })
    .then(() => {
        console.log("内部第一个then2");
    })
    .then(() => {
        console.log("内部第二个then2");
    });
})
.then(() => {
    console.log("外部第二个then");
});
